/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.zhpan.bannerview;

import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.ImageInfo;
import ohos.media.image.common.Size;

import com.zhpan.bannerview.base.BaseIndicatorComponent;

import java.io.IOException;
import java.io.InputStream;

/**
 * DrawableIndicator
 *
 * @since 2021-03-24
 */
public class DrawableIndicator extends BaseIndicatorComponent implements Component.DrawTask, Component.EstimateSizeListener {

    private int width;
    private int height;
    private int normalMapWidth;
    private int normalMapHeight;
    private int checkedMapWidth;
    private int checkedMapHeight;
    private int mIndicatorPadding;

    private ImageSize normalImageSize;
    private ImageSize checkedImageSize;
    private PixelMapHolder checkedMapHolder;
    private PixelMapHolder normalMapHolder;

    private Paint mPaint = new Paint();

    public DrawableIndicator(Context context) {
        super(context);
        init();
    }

    public DrawableIndicator(Context context, AttrSet attrSet) {
        super(context, attrSet);
        init();
    }

    public DrawableIndicator(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init();
    }

    private void init() {
        mIndicatorPadding = AttrHelper.vp2px(5, getContext());
        setEstimateSizeListener(this);
        addDrawTask(this);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (getPageSize() > 1 && checkedMapHolder != null && normalMapHolder != null) {
            setComponentSize(width, height);
            int pageSize = getPageSize();
            int index;
            int left;
            int top;
            for (index = 0; index < pageSize; index++) {
                int currentPosition = getCurrentPosition();
                if (index < currentPosition) {
                    left = index * (normalMapWidth + mIndicatorPadding);
                    top = height / 2 - normalMapHeight / 2;
                    drawIcon(canvas, normalMapHolder, left, top);
                } else if (index == currentPosition) {
                    left = index * (normalMapWidth + mIndicatorPadding);
                    top = height / 2 - checkedMapHeight / 2;
                    drawIcon(canvas, checkedMapHolder, left, top);
                } else {
                    left = index * mIndicatorPadding + (index - 1) * normalMapWidth + checkedMapWidth;
                    top = height / 2 - normalMapHeight / 2;
                    drawIcon(canvas, normalMapHolder, left, top);
                }
            }
        }
    }

    private void drawIcon(Canvas canvas, PixelMapHolder holder, float left, float top) {
        if (holder == null) {
            return;
        }
        Log.debug("drawIcon", "left = " + left + " top = " + top);
        canvas.drawPixelMapHolder(holder, left, top, mPaint);
    }

    @Override
    public boolean onEstimateSize(int widthSpec, int heightSpec) {
        int widthModel = EstimateSpec.getMode(widthSpec);
        int heightModel = EstimateSpec.getMode(heightSpec);

        if (widthModel == EstimateSpec.PRECISE) {
            width = EstimateSpec.getSize(widthSpec);
        } else {
            int totalPadding = mIndicatorPadding * (getPageSize() - 1);
            int totalMapWidth = checkedMapWidth + (getPageSize() - 1) * normalMapWidth;
            width = totalPadding + totalMapWidth;
        }

        if (heightModel == EstimateSpec.PRECISE) {
            height = EstimateSpec.getSize(heightSpec);
        } else {
            height = Math.max(normalMapHeight, checkedMapHeight);
        }
        Log.debug("onEstimateSize", "width = " + width + " height = " + height);
        return false;
    }

    public void setNormalImageSize(ImageSize size) {
        this.normalImageSize = size;
    }

    public void setCheckedImageSize(ImageSize size) {
        this.checkedImageSize = size;
    }

    /**
     * ResourceTable.Media_heart_empty
     * ResourceTable.Media_heart_red
     *
     * @param normalResId 參數
     * @param checkedResId 參數
     */
    public void setMediaResId(int normalResId, int checkedResId) {
        if (normalResId <= 0 || checkedResId <= 0) {
            return;
        }

        PixelMap normalMap = readPixelMap(normalResId, normalImageSize);
        PixelMap checkedMap = readPixelMap(checkedResId, checkedImageSize);
        createPixelMapHolder(normalMap, checkedMap);
        postLayout();
        invalidate();
    }

    private void createPixelMapHolder(PixelMap normalPixelMap, PixelMap checkedPixelMap) {
        if (normalPixelMap == null || checkedPixelMap == null) {
            return;
        }
        try {
            ImageInfo normalInfo = normalPixelMap.getImageInfo();
            if (normalInfo != null) {
                Size size = normalInfo.size;
                normalMapWidth = size.width;
                normalMapHeight = size.height;
            }
            normalMapHolder = new PixelMapHolder(normalPixelMap);

            ImageInfo checkedImageInfo = checkedPixelMap.getImageInfo();
            if (checkedImageInfo != null) {
                Size size = checkedImageInfo.size;
                checkedMapWidth = size.width;
                checkedMapHeight = size.height;
            }
            checkedMapHolder = new PixelMapHolder(checkedPixelMap);
        } catch (Exception e) {
            e.printStackTrace();
            Log.debug("redBitmap", "width = " + width + " height = " + height);
        }
    }

    private PixelMap readPixelMap(int resId, ImageSize size) {
        if (resId <= 0) {
            return null;
        }
        InputStream is = null;
        try {
            // 读取资源
            is = getResourceManager().getResource(resId);
            // 创建ImageOptions
            ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
            sourceOptions.formatHint = "image/jpg";
            // 创建ImageSource
            ImageSource imageSource = ImageSource.create(is, sourceOptions);
            // 创建解码器DecodingOptions
            ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();

            if (size != null) {
                Size s1 = new Size();
                // 缩放操作
                if (size.width > 0) {
                    s1.width = size.width;
                }
                if (size.height > 0) {
                    s1.height = size.height;
                }
                decodingOptions.desiredSize = s1;
            }
            // 创建mapX
            return imageSource.createPixelmap(decodingOptions);
        } catch (IOException | NotExistException e) {
            e.printStackTrace();
            Log.error("getMediaResource", "red resource error --> " + e.getMessage());
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * ImageSize
     *
     * @since 2021-03-24
     */
    public static class ImageSize {
        private int width;
        private int height;

        /**
         * ImageSize
         *
         * @param width 參數
         * @param height 參數
         */
        public ImageSize(int width, int height) {
            this.width = width;
            this.height = height;
        }
    }

}
